// 
// SMS Notifier
// 
// By Aali Alikoski (aali@microsoft.com, http://blogs.msdn.com/aalialikoski)
// Originally developed as a sample for demonstrating Windows Mobile 5 managed APIs
// at Tampere University of Technology mobile development seminar
//

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.WindowsMobile.Status;
using Microsoft.WindowsMobile.PocketOutlook;

namespace SMSNotifier
{
    public partial class Form1 : Form
    {
        SystemState missedCalls = new SystemState(SystemProperty.PhoneMissedCall);
        SMSsettings config;
        int numberOfMissedCalls;
        Boolean bInitializingControlValues = false;
        
        public Form1()
        {
            InitializeComponent();
            config = SMSsettings.ReadFromFile(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\SMSNotifierSettings.xml");
        }

        private void chkAppendNextFreeSlot_CheckStateChanged(object sender, EventArgs e)
        {
            txtFreeSlotText.Enabled = chkAppendNextFreeSlot.Checked;
            ControlvalueChanged(null, null);
        }

        private void chkSendSMS_CheckStateChanged(object sender, EventArgs e)
        {
            txtMessageToSend.Enabled = chkSendSMS.Checked;
            chkIfActiveAppointment.Enabled = chkSendSMS.Checked;
            chkIfBusyAppointment.Enabled = chkSendSMS.Checked;
            chkAppendNextFreeSlot.Enabled = chkSendSMS.Checked;
            txtFreeSlotText.Enabled = chkSendSMS.Checked;
            chkAddMissedCallToCalendar.Enabled = chkSendSMS.Checked;
            ControlvalueChanged(null, null);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            bInitializingControlValues = true;
            _BindSettingsToControlvalues(config);
            bInitializingControlValues = false;
            missedCalls.Changed += new ChangeEventHandler(missedCalls_Changed);
            lblVersion.Text = "Version: " + GetVersionString();
        }

        private String GetVersionString()
        {
            Version v = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
            return v.Major + "." + v.Minor; // Omit the rest for now:  +"." + v.Revision + "." + v.Build;
        }

        void missedCalls_Changed(object sender, ChangeEventArgs args)
        {
            try
            {
                // Only react when the number of missed calls counter goes up.
                // It seems to go down when the user calls back the previously unanswered caller!
                if (numberOfMissedCalls < SystemState.PhoneMissedCalls)
                {
                    Contact caller = SystemState.PhoneLastIncomingCallerContact;
                    if (null != caller) // We know who the caller is as a Contact
                    {
                        string message = "";
                        Boolean bSend = true;
                        if (chkSendSMS.Checked)
                        {
                            bSend = _ShouldSMSBeSent();
                            if (bSend)
                            {
                                message = txtMessageToSend.Text;
                                if (chkAppendNextFreeSlot.Checked)
                                {
                                    message += " ";
                                    message += _GetNextFreeSlotText(txtFreeSlotText.Text);
                                }
                                _SendReplySMSToCaller(SystemState.PhoneLastIncomingCallerNumber, message);
                            }
                        }
                        else
                        {
                            bSend = false;
                        }
                        if (chkAddMissedCallToCalendar.Checked)
                            _CreateCalendarAppointment(caller, message, SystemState.PhoneLastIncomingCallerNumber, bSend);
                    }
                    else
                    {   // Caller is not a contact, but we know the number
                        string message = "";
                        Boolean bSend = true;
                        if (chkSendSMS.Checked)
                        {
                            bSend = _ShouldSMSBeSent();
                            if (bSend)
                            {
                                message = txtMessageToSend.Text;
                                if (chkAppendNextFreeSlot.Checked)
                                {
                                    message += " ";
                                    message += _GetNextFreeSlotText(txtFreeSlotText.Text);
                                }
                                _SendReplySMSToCaller(SystemState.PhoneLastIncomingCallerNumber, message);
                            }
                        }
                        else
                        {
                            bSend = false;
                        }
                        if (chkAddMissedCallToCalendar.Checked)
                            _CreateCalendarAppointment(null, message, SystemState.PhoneLastIncomingCallerNumber, bSend);
                    }
                }
            }
            catch { }
            finally
            {
                numberOfMissedCalls = SystemState.PhoneMissedCalls;
            }
        }

        private Boolean _ShouldSMSBeSent()
        {
            Boolean bSend = false;
            if (chkIfActiveAppointment.Checked)
            {
                bSend = false;
                Appointment a = SystemState.CalendarAppointment;
                if (a != null)
                {
                    if (chkIfBusyAppointment.Checked)
                    {
                        if (a.BusyStatus == BusyStatus.Busy ||
                            a.BusyStatus == BusyStatus.OutOfOffice)
                        {
                            bSend = true;
                        }
                    }
                    else
                    {
                        bSend = true;
                    }
                }
            }
            else
            {
                bSend = true;
            }
            return bSend;
        }

        private string _GetNextFreeSlotText(string formatString)
        {
            // TODO: what if we have multiple appointments either 
            // simultaneously or adjacent to each other?
            Appointment a = SystemState.CalendarAppointment;
            string s = "";
            if (a != null)
            {
                DateTime dtEnd = a.End;
                s = string.Format(formatString, dtEnd.ToShortTimeString());
            }
            return s;
        }

        private void _CreateCalendarAppointment(Contact caller, string SMSMessage, string SMSNumber, Boolean SMSWasSent)
        {
            OutlookSession s = new OutlookSession();
            Appointment app = new Appointment();
            app.BusyStatus = BusyStatus.Free;
            app.ReminderSet = false;
            app.Start = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Utc);
            app.Duration = TimeSpan.FromMinutes(1);
            string body = "";
            if (caller != null) // we know the caller as a Contact
            {
                app.Subject = "Call from " + caller.FirstName + " " + caller.LastName;
                body = "Call from " + caller.FirstName + " " + caller.LastName + _GetTitleAndCompany(caller) + " was missed. ";
            }
            else // we know just the phone number
            {
                app.Subject = "Call from " + SMSNumber + " (not in Contacts)";
                body = "Call from " + SMSNumber + " (not in Contacts) was missed. ";
            }
            if (SMSWasSent)
                body += "An SMS message was sent to " + SMSNumber + ": " + SMSMessage;
            app.Body = body;
            s.Appointments.Items.Add(app);
        }

        private string _GetTitleAndCompany(Contact caller)
        {
            string s="";

            string[] p = new string[]{caller.JobTitle, caller.CompanyName};
            foreach (string ps in p)
            {
                if (ps != string.Empty)
                    if (s.Length == 0)
                        s = ps;
                    else
                        s += ", " + ps;
            }
            if (s.Length > 0)
                s = " (" + s + ")";
            return s;
        }

        private void _SendReplySMSToCaller(string CallerNumber, string text)
        {
            OutlookSession s = new OutlookSession();
            SmsAccount acct = s.SmsAccount;
            // Strip away space, parenthesis and minus, they seem to affect the sending of SMS
            SmsMessage sms = new SmsMessage(CallerNumber.Replace(" ", "").Replace("(", "").Replace(")", "").Replace("-", ""), text);
            acct.Send(sms);
        }

        private void chkIfActiveAppointment_CheckStateChanged(object sender, EventArgs e)
        {
            chkIfBusyAppointment.Enabled = chkIfActiveAppointment.Checked;
        }

        private void _BindControlvaluesToSettings(SMSsettings s)
        {
            s.AddMissedCallInfoToCalendar = chkAddMissedCallToCalendar.Checked;
            s.AppendNextFreeSlotMessage = chkAppendNextFreeSlot.Checked;
            s.FreeSlotTextFormat = txtFreeSlotText.Text;
            s.SendSMSOnlyWhenActiveAppointment = chkIfActiveAppointment.Checked;
            s.SendSMSOnlyWhenBusyAppointment = chkIfBusyAppointment.Checked;
            s.SendSMSToUnansweredCallers = chkSendSMS.Checked;
            s.SMSMessageToSend = txtMessageToSend.Text;
            s.Save();
        }

        private void _BindSettingsToControlvalues(SMSsettings s)
        {
            chkAddMissedCallToCalendar.Checked = s.AddMissedCallInfoToCalendar;
            chkAppendNextFreeSlot.Checked = s.AppendNextFreeSlotMessage;
            txtFreeSlotText.Text = s.FreeSlotTextFormat;
            chkIfActiveAppointment.Checked = s.SendSMSOnlyWhenActiveAppointment;
            chkIfBusyAppointment.Checked = s.SendSMSOnlyWhenBusyAppointment;
            chkSendSMS.Checked = s.SendSMSToUnansweredCallers;
            txtMessageToSend.Text = s.SMSMessageToSend;
        }

        private void ControlvalueChanged(object sender, EventArgs e)
        {
            if (!bInitializingControlValues)
                _BindControlvaluesToSettings(config);
        }
    }
}